<template>
  <div class="svgaEffectCommon" ref="svgaEffectCommon" :style="cStyle"></div>
</template>

<script>
import SVGA from 'svgaplayerweb';

export default {
  name: 'svgaEffectCommon',
  data() {
    return {
      // 动画是否加载完毕
      // 非循环情况下需要用到该字段
      isAniLoaded: false,
      // 标识父组件是否需要播放动画
      // 非循环情况下需要用到该字段
      needPlayAni: false,
    };
  },
  // 定义属性: configObj 对象类型
  // configObj取值举例：{svgaPath:'',cWidth: 0,cHeight: 0,top: 0,left:0,zIndex:0}
  // svga文件路径(必传): svgaPath
  // 容器宽高、位置、层级：cWidth、cHeight、top、left、zIndex
  // ----------------------------
  // 定义属性：needLoop 布尔类型
  // 控制是否循环播放SVGA动画 默认是循环的
  // 不循环的情况下：1、动画只播放一次 2、播放完毕后触发事件svgaEffectCommonFinished
  // 3、动画需要手动触发播放
  // ----------------------------
  // 定义属性：rangeStr 字符串类型
  // 只有非循环模式下才能使用该属性
  // 控制是否播放某个区间范围内的动画,空字符串标识否
  // 区间单位：帧
  // 例子：取值'0,10' 表示播放0-10帧的动画
  props: {
    configObj: {
      type: Object,
      default: () => {
        return {
          svgaPath: '',
          cWidth: 0,
          cHeight: 0,
          top: 0,
          left: 0,
          zIndex: 0,
        };
      },
    },
    needLoop: {
      type: Boolean,
      default: true,
    },
    rangeStr: {
      type: String,
      default: '',
    },
  },
  computed: {
    // 定义计算属性cStyle: 容器Dom的行内样式
    // 根据configObj计算cStyle
    cStyle() {
      const {
        cWidth, cHeight, top, left, zIndex,
      } = this.configObj;
      // 定义包含有效属性的对象: activeObj
      // 取值不为0或空字符串的变量加入到activeObj属性中
      let activeObj;
      if (cWidth) {
        activeObj = {
          width: `${cWidth}px`,
        };
      }
      if (cHeight) {
        activeObj = {
          ...activeObj,
          height: `${cHeight}px`,
        };
      }
      if (top) {
        activeObj = {
          ...activeObj,
          top: `${top}px`,
        };
      }
      if (left) {
        activeObj = {
          ...activeObj,
          left: `${left}px`,
        };
      }
      if (zIndex) {
        activeObj = {
          ...activeObj,
          zIndex,
        };
      }
      return activeObj;
    },
  },
  beforeDestroy() {
    // 销毁SVGA动画
    if (this.SVGAPlayer) {
      this.SVGAPlayer.stopAnimation();
      this.SVGAPlayer.clear();
      this.SVGAPlayer = null;
    }
  },
  watch: {
    // isAniLoaded和needPlayAni都为true时才能播放动画
    // 分别监听isAniLoaded和needPlayAni的变化
    isAniLoaded(newVal) {
      if (newVal && this.needPlayAni) {
        this.playAnimation();
      }
    },
    needPlayAni(newVal) {
      if (newVal && this.isAniLoaded) {
        this.playAnimation();
      }
    },
  },
  created() {},
  mounted() {
    this.$nextTick(() => {
      this.SVGAPlayer = new SVGA.Player(this.$refs.svgaEffectCommon);
      // 不循环的情况下 动画只执行一次
      if (!this.needLoop) {
        this.SVGAPlayer.loops = 1;
      }
      this.$svgaParser.load(
        this.configObj.svgaPath,
        (videoItem) => {
          this.SVGAPlayer.setVideoItem(videoItem);
          // 循环的情况下 动画会自动播放
          if (this.needLoop) {
            this.SVGAPlayer.startAnimation();
          }
          // 不循环的情况下 动画播放结束会触发事件、并设置isAniLoaded为true
          if (!this.needLoop) {
            this.isAniLoaded = true;
            this.SVGAPlayer.onFinished(() => {
              this.$emit('svgaEffectCommonFinished');
            });
          }
        },
        (err) => {
          console.log(err);
          return Promise.reject(err);
        },
      );
    });
  },
  methods: {
    // 父组件通知子组件可以播放动画了
    canPlayAni() {
      this.needPlayAni = true;
    },
    // 播放动画
    // 只有非循环模式下用到
    playAnimation() {
      if (!this.SVGAPlayer) {
        return;
      }
      if (this.rangeStr) {
        const rangeArr = this.rangeStr.split(',');
        this.SVGAPlayer.startAnimationWithRange({
          location: rangeArr[0],
          length: rangeArr[1] - rangeArr[0],
        });
      } else {
        this.SVGAPlayer.startAnimation();
      }
    },
    // 获取 SVGAPlayer 实例
    getSVGAPlayer() {
      return this.SVGAPlayer;
    },
  },
};
</script>

<style lang="less" scoped>
.svgaEffectCommon {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
}
</style>
